﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Xml.Linq;
using Lightray.Hattrick.ChppLib;
using Lightray.Hattrick.ChppLib.EntityTypes;

namespace Lightray.Hattrick
{

    public class SeniorTeamModel : BaseTeamModel
    {
        private EntityCollection<Player> _oldPlayers, _currentPlayers;                
        private DataTable _dataSource;
  
        #region DataTable columns
        
        private const string COL_STAMINA = "STM";
        private const string COL_FORM = "FRM";        
        private const string COL_EXPERIENCE = "XP";
        private const string COL_LEADERSHIP = "LDR";

        private const string COL_NATIONALITY = "NAT";

        private const string COL_TSI = "TSI";
        private const string COL_SALARY = "SALARY";
        
        private const string COL_FORWARD_SCORE = "FWD_SCR";
        private const string COL_WINGER_SCORE = "WNG_SCR";
        private const string COL_PLAYMAKER_SCORE = "IM_SCR";
        private const string COL_WINGBACK_SCORE = "WB_SCR";
        private const string COL_DEFENDER_SCORE = "CD_SCR";
        private const string COL_KEEPER_SCORE = "GK_SCR";
        private const string COL_SET_PIECES_SCORE = "SP_SCR";
        private const string COL_PENALTY_SHOT_SCORE = "PT_SCR";
        private const string COL_CAPTAIN_SCORE = "CPT_SCR";

        #endregion

        public override bool HasProgressReport
        {
            get { return pastWeekDataAvailable(); }
        }

        public SeniorTeamModel(ITrickStorageEntry newEntry, ITrickStorageEntry oldEntry)
        {
            _currentPlayers = instancePlayers(newEntry.MyPlayers);
            _oldPlayers = instancePlayers(oldEntry.MyPlayers);

            if (minimalDataAvailable())
                workData();
        }

        public override ModelColumnDescription GetColumnDescription(string columnName)
        {
            switch (columnName)
            {
                case COL_FORWARD_SCORE:
                case COL_WINGER_SCORE:
                case COL_PLAYMAKER_SCORE:
                case COL_WINGBACK_SCORE:
                case COL_DEFENDER_SCORE:
                case COL_KEEPER_SCORE:
                case COL_SET_PIECES_SCORE:
                case COL_PENALTY_SHOT_SCORE:
                case COL_CAPTAIN_SCORE:
                    return ModelColumnDescription.SkillScore;

                case COL_STAMINA:
                case COL_FORM:             
                case COL_EXPERIENCE:
                case COL_LEADERSHIP:
                    return ModelColumnDescription.Skill;
               
                case COL_TSI:
                    return ModelColumnDescription.TSI;
               
                case COL_SALARY:
                    return ModelColumnDescription.Salary;            

                case COL_NATIONALITY :
                    return ModelColumnDescription.Nationality;
            }

            return base.GetColumnDescription(columnName);
        }

        public override PlayerRole GetRoleColumnName(string columnName)
        {
            switch (columnName)
            {
                case COL_FORWARD_SCORE:
                    return PlayerRole.Forward;
                case COL_WINGER_SCORE:
                    return PlayerRole.Winger;
                case COL_PLAYMAKER_SCORE:
                    return PlayerRole.Playmaking;
                case COL_WINGBACK_SCORE:
                    return PlayerRole.Wingback;
                case COL_DEFENDER_SCORE:
                    return PlayerRole.Defender;
                case COL_KEEPER_SCORE:
                    return PlayerRole.Goalkeeper;
                case COL_SET_PIECES_SCORE:
                    return PlayerRole.SetPieces;
                case COL_PENALTY_SHOT_SCORE:
                    return PlayerRole.PenaltyTaker;
                case COL_CAPTAIN_SCORE:
                    return PlayerRole.Captain;
            }

            throw new Exception("Invalid column name");
        }    

        public override String[] UnlockedSkillsFromRow(DataRowView dataRowView)
        {
            throw new NotImplementedException();
        }
       
       protected override string columnNameFromProgressRecord(ProgressRecord progressRecord)
        {
            switch (progressRecord.AffectedAttribute)
            {
                case ProgressAttributes.TSI:
                    return COL_TSI;
                case ProgressAttributes.Salary:
                    return COL_SALARY;
                case ProgressAttributes.Skill:

                    switch (progressRecord.AffectedSkill)
                    {
                        case Skill.Form:
                            return COL_FORM;
                        case Skill.Experience:
                            return COL_EXPERIENCE;
                        case Skill.Leadership:
                            return COL_LEADERSHIP;
                        case Skill.Stamina:
                            return COL_STAMINA;                  
                    }
                    break;

                case ProgressAttributes.RoleScore:

                    switch (progressRecord.AffectedRole)
                    {
                        case PlayerRole.Forward:
                            return COL_FORWARD_SCORE;
                        case PlayerRole.Winger:
                            return COL_WINGER_SCORE;
                        case PlayerRole.Playmaking:
                            return COL_PLAYMAKER_SCORE;
                        case PlayerRole.Wingback:
                            return COL_WINGBACK_SCORE;
                        case PlayerRole.Defender:
                            return COL_DEFENDER_SCORE;
                        case PlayerRole.Goalkeeper:
                            return COL_KEEPER_SCORE;
                        case PlayerRole.SetPieces:
                            return COL_SET_PIECES_SCORE;
                        case PlayerRole.PenaltyTaker:
                            return COL_PENALTY_SHOT_SCORE;
                        case PlayerRole.Captain:
                            return COL_CAPTAIN_SCORE;
                    }
                    break;
            }

            return base.columnNameFromProgressRecord(progressRecord);
        }
         
        private EntityCollection<Player> instancePlayers(XDocument xml)
        {
            return xml != null ? Player.FromXml(xml) : null;
        }

        private bool minimalDataAvailable()
        {
            return _currentPlayers != null;
        }

        private bool pastWeekDataAvailable()
        {
            return _oldPlayers != null;
        }

        private void workData()
        {
            buildDataSource();
            fillDataSource();
            buildProgressReport();
            Data = new DataView(_dataSource);
        }

        private void buildProgressReport()
        {
            if (pastWeekDataAvailable())
                _progressReport = ProgressReport.GetTeamProgressReport(_currentPlayers, _oldPlayers);
        } 

        private void buildDataSource()
        {
            _dataSource = new DataTable();
            _dataSource.Columns.AddRange(new DataColumn[] 
            {
                new DataColumn(COL_NAME,  typeof(string)),
                new DataColumn(COL_AGE,   typeof(HattrickAge)),
                new DataColumn(COL_NATIONALITY,   typeof(Country)),                
                new DataColumn(COL_STAMINA,   typeof(SkillLevel)),
                new DataColumn(COL_FORM,   typeof(SkillLevel)),
                new DataColumn(COL_CARDS, typeof(int)),
                new DataColumn(COL_INJURY,   typeof(int)),
                new DataColumn(COL_SCORING,   typeof(SkillLevel)),
                new DataColumn(COL_PLAYMAKING,    typeof(SkillLevel)),
                new DataColumn(COL_WINGER,   typeof(SkillLevel)),
                new DataColumn(COL_PASSING,   typeof(SkillLevel)),
                new DataColumn(COL_DEFENDING,   typeof(SkillLevel)),
                new DataColumn(COL_KEEPING,    typeof(SkillLevel)),
                new DataColumn(COL_SETPIECES,    typeof(SkillLevel)),                
                new DataColumn(COL_EXPERIENCE,    typeof(SkillLevel)),
                new DataColumn(COL_LEADERSHIP,   typeof(SkillLevel)),                
                new DataColumn(COL_FORWARD_SCORE,   typeof(double)),
                new DataColumn(COL_WINGER_SCORE,   typeof(double)),
                new DataColumn(COL_PLAYMAKER_SCORE,  typeof(double)),
                new DataColumn(COL_WINGBACK_SCORE,  typeof(double)),
                new DataColumn(COL_DEFENDER_SCORE,  typeof(double)),
                new DataColumn(COL_KEEPER_SCORE,  typeof(double)),
                new DataColumn(COL_SET_PIECES_SCORE,  typeof(double)),
                new DataColumn(COL_PENALTY_SHOT_SCORE,  typeof(double)),
                new DataColumn(COL_CAPTAIN_SCORE, typeof(double)),
                new DataColumn(COL_TSI,   typeof(int)),
                new DataColumn(COL_SPECIALITY,   typeof(Specialty)),
                new DataColumn(COL_SALARY,   typeof(float)),
                new DataColumn(COL_PLAYER_INSTANCE, typeof(BasicPlayer)),
            });
        }

        private void fillDataSource()
        {
            _dataSource.BeginLoadData();
            foreach (var player in _currentPlayers)
            {
                PlayerScores scores = new PlayerScores(player);                
                _dataSource.Rows.Add(   player.Name,
                                        player.Age,
                                        player.Birthplace,
                                        player.Stamina,
                                        player.Form,
                                        player.Cards,
                                        player.InjuryLevel,
                                        player.Scoring,
                                        player.Playmaking,
                                        player.Winger,
                                        player.Passing,
                                        player.Defending,
                                        player.Keeper,
                                        player.SetPieces,
                                        player.Experience,
                                        player.Leadership,
                                        scores.ForwardScore,
                                        scores.WingerScore,
                                        scores.PlaymakerScore,
                                        scores.WingbackScore,
                                        scores.DefenderScore,
                                        scores.GoalkeeperScore,
                                        scores.SetPiecesScore,
                                        scores.PenaltyShooterScore,
                                        scores.CaptainScore,
                                        player.TSI,
                                        player.Specialty,
                                        player.Salary,
                                        player);
            }
            _dataSource.EndLoadData();
        }
    }  
}
